Technical Note TN2095
Authorization for Everyone



目次

Mac OS X はさまざまな環境で使用できるマルチユーザシステムで、それぞれの環境では互いに大きく異なる認証要件を使用できます。たとえば、叔父さんの家に設置されている iMac は完全にオープンなシステムである一方で、大学の研究室に設置されている iMac はきわめて厳しい制約が課されているという具合です。

アプリケーションデベロッパの皆さまは、認証に関して、それらの環境すべてに適した決定を下すことはできません。むしろ、そのような決定はシステム管理者に任せるべきです。また、安全かつ標準的な方法で認証を行う認証サービスを利用することもできます。

このテクニカルノートは、Mac OS X アプリケーションデベロッパの方を対象にしています。とりわけ、これまで認証サービスを利用したことがないデベロッパの方は注目です。従来のお客さまに対して、手間をかけずにそのまま利用できるという利便性を損なわずに、認証サポートをアプリケーションに追加する方法を説明します。

[2003 年 10 月 9 日]



はじめに

Mac OS X 向けにアプリケーションを開発しているデベロッパのほとんどは、システムの特権モデルが作業の遂行の妨げになるときにだけ認証問題を考えます。そのようなアプリケーション(Authorization Services のドキュメントでは system-restricted(システム制限型)アプリケーションと呼ばれている)を実装するために認証サービスを利用することは十分に想定されており、その方法を明確に示す 2 つのサンプルプログラム(AuthSampleMoreAuthSample)もあります。

しかし、認証サービスはそれだけが目的ではありません。Mac OS X 向けのアプリケーションを作成するときには、たとえそれにシステム制限型機能がない場合でも、認証サービスを利用できるかどうか考えるべきです。特に、システム管理者がアプリケーションの機能を特定のユーザのサブセットに限定したい可能性があるかどうかを考えてください。以下の例を検討してみましょう。

  • CD 作成アプリケーションを開発していると仮定します。学校のシステム管理者は、すべてのユーザがデータ CD を作成できるようにする一方で、オーディオ CD の作成を特定のユーザに限定したいかもしれません。
  • 一般消費者向けのテレビチューナーアプリケーションを作成しているとしましょう。親(この場合のシステム管理者)は、子供に特定のチャネルを見せたくないかもしれません。

重要なことなので強調しておきますが、システムの特権モデルはこのような行動を妨げるものではありません。たとえば、CD ドライバに関して言えば、どんなユーザにもディスクの作成が許されています。しかし、認証サービスを利用して、アプリケーションに認証レイヤーを追加することができます。これは self-restricted(自己制限型)アプリケーションと呼ばれています。

自己制限型アプリケーションを作成できることは、これまでも認証サービスの特徴の一部でした。しかし、Mac OS X v10.3 以前には、自己制限型アプリケーションの作成と、自分でシステムを管理するユーザが期待する、手間をかけずに利用できる(すなわち、パスワードダイアログがない)利便性の維持を、同時に実現する手段はありませんでした。Mac OS X v10.3 では、両者の利点を同時に提供できる新しい認証サービスルーチンが用意されています。

  • 認証サービスを利用して、システム管理者が(もしいれば)、アプリケーションの特定の要素へのアクセスを制限できます。
  • しかしデフォルトでは、これらの制限によって、システムを自分で管理するユーザの利便性が損なわれることはありません。

以下の 8 つのセクションでは、この理想的なソリューションを Mac OS X v10.3 で実現する方法を説明します。最後のセクション「旧システムのサポート」では、旧バージョンの Mac OS X で同様のソリューションを実現する方法を説明します。


重要:
このテクニカルノートに掲載したコード例は、「参考資料」セクションにリストアップした URL からダウンロードできます。



先頭に戻る

Mac OS X v10.3 のサポート

以下のセクションでは、Mac OS X v10.3 上で認証サービスを利用して、システム管理者が設定しないかぎりパスワードダイアログボックスを表示しない自己制限型のアプリケーションを実装する方法を説明します。第一歩はカスタムの認証権限を定義することです。次に、認証権限を取得できるようにアプリケーションを変更します。認証ダイアログがときどき表示される理由を理解するには、認証ポリシーデータベースについて理解する必要があります。このデータベースについて理解すれば、手動またはプログラムでカスタム権限に関する権限指定を含むようにデータベースを変更することができます。最後に、このテクニックを利用する際の 2 つの注意すべき点、すなわちカスタム権限に対するローカライズされたプロンプトをサポートする方法と、認証サービスのバグを回避する方法について説明します。

先頭に戻る

認証権限の定義

最初の一歩は、システム管理者が制限したいと考えられるユーザレベルの操作を割り出し、それぞれの認証対象操作について権限名を定義することです。権限名は、逆 DNS 表記法を使用して、階層構造の名前空間を形成します。この例では、リスト 1 に示す権限名を使用します。まず会社名(com.apple.)、次に社内の所属部署(dts.)、さらに製品名(AuthForAll.)、最後に製品の操作(この例では、架空の操作 Alpha としました)という順番になっています。



リスト 1 権限名の定義

const char kAlphaRightName[] = "com.apple.dts.AuthForAll.Alpha";



一般に、認証対象操作ごとに 1 つの権限を定義します。たとえば、CD 作成アプリケーションの例で言えば、com.SurfSoftware.SurfBurner.Burn.Audiocom.SurfSoftware.SurfBurner.Burn.Data を定義します。

先頭に戻る

権限の取得

次のステップは、操作を実行する前に権限を取得するようにコードを変更することです。その一例をリスト 2 に示します。基本的な考え方は、AuthorizationCopyRights を呼び出し、要求したい権限の名前(たとえば、リスト 1 で定義した名前)を渡すことです。AuthorizationCopyRights は、ユーザに代わってその権限の取得を試み(場合によっては、パスワードダイアログを表示します。これについては次のセクションで説明します)、成功したかどうかを示すエラーコードを返します。



リスト 2 権限の取得

extern OSStatus AcquireRight(const char *rightName)
    // このルーチンは認証サービスを呼び出して、
    // 指定した権限を取得する。
{
    OSStatus                         err;
    static const AuthorizationFlags  kFlags = 
                  kAuthorizationFlagInteractionAllowed 
                | kAuthorizationFlagExtendRights;
    AuthorizationItem   kActionRight = { rightName, 0, 0, 0 };
    AuthorizationRights kRights      = { 1, &kActionRight };

    assert(gAuthorization != NULL);

    // アプリケーション固有の権限を要求する。

    err = AuthorizationCopyRights(
        gAuthorization,         // 認証
        &kRights,               // 権限
        NULL,                   // 環境
        kFlags,                 // フラグ
        NULL                    // 認証された権限
    );

    return err;
}



注意:
リスト 2 では、gAuthorization はアプリケーションの認証インスタンスへの参照です。これはリスト 5 の起動コードによって用意されます。


先頭に戻る

認証ポリシーデータベースの概要

コードを上記のように変更して徹底的なテストを行っていると、ある状況下では、管理者のユーザ名とパスワードの入力を求めるダイアログが表示されます。これを再現する簡単な方法は、管理者以外のユーザを作成して、そのユーザとしてログインし、アプリケーションを起動して、認証対象操作を実行することです。一般消費者向けのアプリケーションを作成している方であれば、この認証ダイアログはおそらく望ましいものではありません。しかし、このダイアログが表示されないようにする前に、それが表示される理由を理解する必要があります。

Mac OS X 上での認証は、ポリシーデータベースによって制御されます。現行バージョンの Mac OS X では、このデータベースは「/etc/authorization」にあります。データベースの形式は、そのファイルの先頭にあるコメントに記載されています。

警告:
ポリシーデータベースの場所と形式は変更される可能性があります。Mac OS X の将来のリリースとのバイナリ互換性を維持したい場合には、この情報をアプリケーションのコードに埋め込まないでください。

実際、ポリシーデータベースの形式は Mac OS X v10.3 で変更されました。このセクションでは新しい形式を使用していますが、ここで述べた考え方を古い形式に適用するのは比較的簡単です。


カスタム権限を要求すると認証サービスによってダイアログが表示される理由を理解するには、ポリシーデータベースの仕組みを少し理解する必要があります。リスト 3 に、Mac OS X v10.3 にインストールされているポリシーデータベースの抜粋を示します。



リスト 3 ポリシーデータベースの抜粋

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC [...]>
<plist version="1.0">
<dict>
    [...]
    <key>rights</key>
    <dict>
        <key>system.device.dvd.setregion.initial</key>
        <dict>
            <key>class</key>
            <string>user</string>
            <key>comment</key>
            <string>Used by the dvd player to set the 
regioncode the first time.Note that changed the region code 
after it has been set requires a different right 
(system.device.dvd.setregion.change) Credentials remain valid 
indefinitely after they've been obtained.An acquired 
credential is shared amongst all clients.</string>
            <key>group</key>
            <string>admin</string>
            <key>mechanisms</key>
            <array>
                <string>builtin:authenticate</string>
            </array>
            <key>shared</key>
            <true/>
        </dict>
        [...]
        <key>config.add.</key>
        <dict>
            <key>class</key>
            <string>allow</string>
            <key>comment</key>
            <string>wildcard right for adding rights.Anyone 
is allowed to add any (non-wildcard) rights</string>
        </dict>
        [...]
        <key></key>
        <dict>
            <key>class</key>
            <string>rule</string>
            <key>comment</key>
            <string>All other rights will be matched by this rule.
Credentials remain valid 5 minutes after they've been obtained.
An acquired credential is shared amongst all clients.
            </string>
            <key>rule</key>
            <string>default</string>
        </dict>
        [...]
    </dict>
    <key>rules</key>
    <dict>
        [...]
    </dict>
</dict>
</plist>


ポリシーデータベースは、rightsrules という 2 つのディクショナリで構成されています。本稿では、rights ディクショナリを中心に取り上げます。これには、権限指定と呼ばれる一連のキーと値のペアが含まれています。キーは権限名で、値はその権限に関する情報です。権限の情報には、ユーザが権限を取得するためにしなければならないことの説明などが含まれています。リスト 3 には 3 つの権限が示されています。

  • system.device.dvd.setregion.initial は、ユーザが DVD ドライブの初期リージョンコードを設定できるかどうかを制御します。デフォルトでは、ユーザが DVD リージョンを設定するには、(admin グループの)管理者であることを証明する必要があります。
  • config.add.ワイルドカード型の権限指定(末尾はドット)で、名前が「config.add.」で始まる権限とマッチします。これは、ユーザがポリシーデータベースに権限指定を追加できるかどうかを制御します。デフォルトでは、任意のユーザが権限指定を追加することが認められています。
  • 空のキー文字列を持った権限指定は、デフォルト権限指定と呼ばれます。ユーザがこの権限を取得するには、デフォルト条件を満たす必要があります。現行バージョンの Mac OS X のデフォルトでは、管理者であること証明することです。

プログラムが権限を要求すると、認証サービスによって次のアルゴリズムが実行されます。

  1. ポリシーデータベースで、キーが権限名と正確にマッチする権限指定を検索します。
  2. 検索に失敗すると、ポリシーデータベースで、キーが権限名とマッチするワイルドカード型権限指定を検索します。該当する複数の指定が見つかった場合には、一番長いキーが使用されます。
  3. この検索も失敗すると、デフォルト権限指定が使用されます。

適切な権限指定が見つかったら、認証サービスによってその指定が評価され、権限を与えるかどうかが決定されます。これは場合によっては簡単ですが(リスト 3 の例では、config.add. は必ず与えられます)、それ以外の場合にはもっと複雑になることもあります(たとえば、DVD リージョンを設定するには、管理者パスワードを入力する必要があるなど)。

デフォルト権限があると、カスタム権限を使用する自己制限型プログラムでは注意が必要です。リスト 12 のコードを考えてみます。要求された権限の com.apple.dts.AuthForAll.Alpha は、ポリシーデータベースのどの権限指定にもマッチしないため、デフォルト権限指定が使用されます。それが理由で、リスト 2 のコードでは管理者パスワードを要求するダイアログが表示されるのです。


注:
お気づきかもしれませんが、リスト 2 のコードで必ずしもパスワードダイアログが表示されるとは限りません。これは、認証資格情報の共有方法によるものです。詳細については、DTS Q&A 1277 Security Credentials を参照してください。


先頭に戻る

ポリシーデータベースの変更

このパスワードダイアログを回避する明らかな方法は、カスタム権限の取得を任意のユーザに明示的に許可する新しい権限指定をポリシーデータベースに追加することです。システム管理者であれば、これは簡単です。ファイルをテキストエディタ(あるいは Property List Editor でも可能)で開き、適切な変更を加え、変更を保存するだけです。たとえば、リスト 1 の権限を任意のユーザが取得できるようにする権限指定を追加するには、リスト 4 のテキストをポリシーデータベースに追加するだけです。



リスト 4 リスト 1 の権限取得を「いつも許可する」権限指定

        [...]
        <key>com.apple.dts.AuthForAll.Alpha</key>
        <dict>
            <key>rule</key>
            <string>allow</string>
        </dict>
        [...]




注:
ポリシーデータベースファイルは、root ユーザのみが書き込み可能です。Terminal で sudo を実行してテキストエディタを使用するか、特権ファイルを保存しようとすると管理者パスワードを要求する GUI テキストエディタ(最新の BBEdit など)を使用して編集することができます。


このアプローチは、アプリケーションの利用者側に腕の良いシステム管理者がいる場合には適切です(たとえば、大学の研究室で使用するようなアプリケーションを販売する場合など)。しかし、専任のシステム管理者がいない大半の Mac ユーザに販売するようなプログラムの場合は適切ではありません。さらに、ポリシーデータベースファイルをプログラムで直接変更するという選択肢はありません。前述のように、データベースの場所と形式は変更される可能性があるからです。

この難問の解決策は、Mac OS X v10.3 で追加された新しい認証データベース API です。

先頭に戻る

プログラムによる権限の追加

リスト 5 のコードは、Mac OS X v10.3 で導入された認証サービスルーチンを使用してポリシーデータベースに権限指定を追加する方法を示します。このコードは比較的単純です。まず、AuthorizationCreate を呼び出して、アプリケーションの認証インスタンスへの参照を作成します。次に、AuthorizationRightGet を呼び出して、そのカスタム権限に合った既存の権限指定があるかどうかを確認します。あれば、コードで何かをすることはありません。システム管理者がすでに独自の権限指定を追加しているか、プログラムが以前に実行されているからです。しかし、カスタム権限に対応した指定がなければ、コードで(AuthorizationRightSet を使用して)その権限を任意のユーザが取得できるようにする指定を作成します。



リスト 5 プログラムによる権限の追加

static OSStatus SetupRight(
    AuthorizationRef    authRef, 
    const char *        rightName, 
    CFStringRef         rightRule, 
    CFStringRef         rightPrompt
)
    // 権限が認証データベースに存在するか確認し、
    // 存在しなければ、権限を作成し、初期値を設定する。
{
    OSStatus err;

    // 権限がすでに定義されているか確認する。

    err = AuthorizationRightGet(rightName, NULL);
    if (err == noErr) {

        // 権限がすでに存在する。システム管理者によって
        // すでに設定されているか、初めての実行ではない
        // 可能性がある。いずれにせよ、ここで行うことは
        // ほかに何もない。

} else if (err == errAuthorizationDenied) {

        // 権限がまだ定義されていない。
        // (rightRule パラメータによって)
        // 呼び出し側が指定したルールに基づいて、
        // 権限定義を作成する。パラメータの値
        // としては kAuthorizationRuleClassAllow
        // (任意のユーザが権限を取得できる)、
        // kAuthorizationRuleAuthenticateAsAdmin
        // (管理ユーザとしての認証を必要とする)、
        // または「AuthorizationDB.h」のほかの値が可能。
        // システム管理者は、この権限を必要に応じて変更できる。

        err = AuthorizationRightSet(
            authRef,                // authRef
            rightName,              // rightName
            rightRule,              // rightDefinition
            rightPrompt,            // descriptionKey
            NULL,                   // bundle, NULL はメインを示す
            NULL                    // localeTableName, NULL は
        );                          // "Localizable.strings" を示す 
                                    

        // 権限を追加する権限自体が、権限によって左右される。
        // この権限を取得できない場合には、
        // 上記のルーチンからエラーが返される。
        // エラーでアプリケーションが起動しないことは避けたいので、
        // エラーを飲み込む。

        if (err != noErr) {
            #if ! defined(NDEBUG)
                fprintf(
                    stderr, 
                    "Could not create default right (%ld)¥n", 
                    err
                );
            #endif
            err = noErr;
        }
    }

    return err;
}

extern OSStatus SetupAuthorization(void)
    // アプリケーションの起動時に呼び出される。
    // 認証サービスに接続して、権限(kActionRightName)が
    // 定義されているか確認する。
{
    OSStatus err;

    // 認証サービスへ接続する。

    err = AuthorizationCreate(NULL, NULL, 0, &gAuthorization);

    // 権限を設定する。

    if (err == noErr) {
        err = SetupRight(
            gAuthorization, 
            kAlphaRightName, 
            CFSTR(kAuthorizationRuleClassAllow), 
            CFSTR("YOU MUST BE AUTHORIZED TO DO ALPHA")
        );
    }
    [...]

    return err;
}



このシーケンスにより、権限指定がポリシーデータベースに追加されるので、システム管理者がいれば、ポリシーデータベースに目を通し、アプリケーションによって作成された権限指定を検討して、その値を適切に設定することができます。リスト 6 はこの権限指定の例を示します。



リスト 6 リスト 5 のコードによって追加された権限指定

        [...]
        <key>com.apple.dts.AuthForAll.Alpha</key>
        <dict>
            <key>default-prompt</key>
            <dict>
                <key></key>
                <string>YOU MUST BE AUTHORIZED TO DO ALPHA</string>
            </dict>
            <key>rule</key>
            <string>allow</string>
        </dict>
        [...] 
        


リスト 5 では示していませんが、AuthorizationRightSet には高い柔軟性があります。最後の 2 つのパラメータにより、権限のプロンプトのローカライズした形式提供することができます。これについては、次のセクションで詳しく説明します。また、3 番目のパラメータは文字列(権限取得に関する共通ルールの名前)またはディクショナリ(権限の取得方法に関する詳細な指定)のいずれでもかまいません。この詳細については、「AuthorizationDB.h」(セキュリティフレームワークの一部)のヘッダコメントを参照してください。

先頭に戻る

ローカライズ

AuthorizationRightSet を呼び出す際には、プロンプトを制御する 3 つのパラメータを渡します。このプロンプトは、ユーザが権限を取得するために認証を行う必要がある場合に表示されます。パラメータは次の 3 つです。

  • descriptionKeyCFStringRef です。
  • bundleCFBundleRef です。
  • localeTableNameCFStringRef です。

bundle および localeTableName パラメータは、プロンプトが格納されているローカライズテーブルファイルを指定します。bundleNULL の場合、ルーチンは(CFBundleGetMainBundle によって返される)メインバンドルを使用します。localeTableNameNULL の場合、ルーチンは指定されたバンドルの「Localizable.strings」ファイルを使用します。

descriptionKey パラメータは、ローカライズテーブルファイル内の文字列を参照するのに使用されます。これが NULL の場合、権限には関連付けられたプロンプトがありません。

NULL 以外の descriptionKey を渡して AuthorizationRightSet を呼び出すと、バンドルのすべてのローカライズ指定を反復処理します。各ローカライズ指定について、適切なローカライズテーブルファイルを探し、そのテーブル内の詳細キーを参照します。その後、結果として見つかった詳細文字列を権限指定の default-prompt ディクショナリに追加します。

たとえば、アプリケーションにローカライズ指定がない場合、リスト 5 のコードは リスト 6 の権限指定を生成します。しかし、English(en)と Australian English(en_AU)の 2 つのローカライズ指定がある場合、リスト 5 のコードは、リスト 7 に示す権限指定を生成します。



リスト 7 リスト 5 のコードによって追加されたローカライズされた権限指定

        [...]
        <key>com.apple.dts.AuthForAll.Alpha</key>
        <dict>
            <key>default-prompt</key>
            <dict>
            <key></key>
            <string>YOU MUST BE AUTHORIZED TO DO ALPHA</string>
            <key>en</key>
            <string>You must be authorized to do alpha.</string>
            <key>en_AU</key>
            <string>Strewth!You must be authorised to do 
alpha.</string>
        </dict>
        <key>rule</key>
        <string>allow</string>
        </dict>
        [...] 



この権限指定を使えば、認証のプロンプトが表示されるときに、オーストラリア英語よりも英語を好むユーザには「You must be authorized to do alpha.」と表示され、英語よりオーストラリア英語を好むユーザには「Strewth!You must be authorised to do alpha.」と表示されます。オーストラリア人にとって、すべての文に間投詞が含まれていることはとても重要です(しかも、「authorised」は「s」で綴られます)。


重要:
リスト 7 に示した権限指定の場合は、ルールによって権限が必ず与えられるため、認証ダイアログは表示されません。認証ダイアログを表示するには、認証ポリシーデータベースを編集して、<string>allow</string><string>authenticate-admin</string> に変更します。




注:
英語よりオーストラリア英語のほうが好みであることをシステムに伝えるには、「システム環境設定」の「言語環境」パネルで項目を並べ替えます。「編集」ボタンをクリックすると表示されるダイアログで、まず Australian English を有効にする必要があります。


プロンプトを選択する際には、完全な文を使用することが重要です。認証ダイアログに表示される文字列は、いくつかの独立した文で構成されるため、プロンプト文字列をそのモデルに適合する必要があります。

最後に、現在のところ、認証サービスはローカライズシノニム (r. 3430642) をサポートしていない点に注意してください。そのために、バンドルのローカライズ用フォルダは「English.lproj」ではなく、「en.lproj」でなければなりません。

先頭に戻る

バンドル参照数の問題

最後にもう 1 つ、AuthorizationRightSet に関して注意すべき点があります。あるバグ(r. 3446163)のために、AuthorizationRightSet は、操作対象バンドルに対する参照数をデクリメントします。AuthorizationRightSet を何度も呼び出すと、バンドル参照数はゼロになり、バンドルが解放されてしまいます。NULLAuthorizationRightSetbundle パラメータに渡すと、メインバンドルが解放され、アプリケーションがすぐにクラッシュしてしまいます。

このバグは、Mac OS X の将来のリリースで修正されます。差し当たり、このバグを回避するには、バンドルの参照数を人為的にインクリメントします。この回避策については、リスト 8 に推奨コードを示します。



リスト 8 参照数バグの推奨回避策

static OSStatus AuthorizationRightSetWithWorkaround(
    AuthorizationRef    authRef,
    const char *        rightName,
    CFTypeRef           rightDefinition,
    CFStringRef         descriptionKey,
    CFBundleRef         bundle,
    CFStringRef         localeTableName
)
    // AuthorizationRightSet には、指定した bundle パラメータ
    // (NULL を指定した場合にはメインバンドル)を
    // 解放してしまうバグがある。
    // NULL を指定して、AuthorizationRightSet を何度も呼び出すと、
    // メインバンドルの参照数がゼロになり、クラッシュする。
    //
    // このルーチンは、バンドルに対してリテイン処理を
    // 行うことでバグを回避する。バグが修正された後でも、
    // 正しく動作するはずである。
    //
    // このテクニックは、スレッドセーフでないため、
    // スレッド環境が非常にシンプルな状態にある
    // アプリケーションの起動時に限定して、この
    // テクニックを使うと良い。
{
    OSStatus        err;
    CFBundleRef     clientBundle;
    CFIndex         originalRetainCount;

    // 有効なバンドルを取得する。

    if (bundle == NULL) {
        clientBundle = CFBundleGetMainBundle();
    } else {
        clientBundle = bundle;
    }
    assert(clientBundle != NULL);

    // 元の参照数を記憶し、リテイン処理を行う。
    // リテイン処理を行うのは、参照数が 1 のときに、
    // バグがまだ存在していたら、次の呼び出しによって
    // 参照数が 0 になり、オブジェクトが解放されるからだ。

    originalRetainCount = CFGetRetainCount(clientBundle);
    CFRetain(clientBundle);

    // そのまま認証サービスを呼び出す。

    err = AuthorizationRightSet(
        authRef, 
        rightName, 
        rightDefinition, 
        descriptionKey, 
        clientBundle, 
        localeTableName
    );

    // 参照数が魔法のように元の値に戻っている場合には、
    // バグに遭遇したということなので、メッセージを表示する。
    // それ以外の場合、バグは修正されているということなので、
    // リテイン処理に対する解放処理を実行して参照数を戻す。

    if ( CFGetRetainCount(clientBundle) == originalRetainCount ) {
        fprintf(
            stderr, 
            "AuthForAll: Working around <rdar://problems/3446163>¥n"
        );
    } else {
        CFRelease(clientBundle);
    }

    return err;
}



先頭に戻る



旧システムのサポート

アプリケーションを旧バージョンの Mac OS X で実行する必要がある場合、前のセクションで説明した認証サービスルーチンは役に立ちません。しかし、旧システムとの互換性が必要な場合に使える戦略が 2 つあります。

  • 新しい認証サービスルーチンの有無を簡単に確認して、存在しなければ、まったく認証を行わないという方法。これには単純さというメリットがありますが、Mac OS X v10.3 に更新していないシステム管理者は、アプリケーションのどの機能を誰が使えるのか管理していません。
  • 認証ポリシーデータベースを直接読み取ることで、AuthorizationRightGet のエミュレートを試みることができます。これは前述のアドバイスと真っ向から矛盾しますが、古いシステムでそれを実行するだけなら容認されます。古いシステムであれば、認証ポリシーデータベースの形式と場所は変わらないからです。新しい認証サービスルーチンが存在する Mac OS X v10.3 以降では、必ず新しいルーチンを使用し、認証ポリシーデータベースの形式に関して何も前提にしてはなりません。

AuthForAll の例は、2 つ目の選択肢を実装する 1 つの方法を示します。この例には、AuthForAll と AuthForAllCompat という 2 つのターゲットが含まれています。最初のターゲットは、Mac OS X v10.3 を必要とするアプリケーションを構築します。これは、このテクニカルノートのサンプルに使用したコードです。2 番目のターゲットは、Mac OS X v10.1 まで遡って実行が可能なアプリケーションを構築し、下位互換性を完全に保った自己制限型アプリケーションを作成する方法を示します。

先頭に戻る



要約

認証サービスにより、どのユーザがどの機能にアクセスできるかをシステム管理者が管理する自己制限型アプリケーションを作成できます。Mac OS X v10.3 を使えば、一般的な顧客が手間をかけずにそのまま使える利便性を損わない認証サービスを実装することができます。認証サービスを採用するのは簡単であり、導入すれば世界中のシステム管理者が幸せになれます。

先頭に戻る



参考資料

Inside Mac OS X:Performing Privileged Operations With Authorization Services

DTS Q&A 1277 Security Credentials

DTS AuthForAll サンプルコード

DTS AuthSample サンプルコード

DTS MoreAuthSample サンプルコード